// 版权所有2009 Go作者。版权所有。
// 此源代码的使用受BSD样式
// 许可证的约束，该许可证可以在许可证文件中找到。

package math

/*
	Floating-point arctangent.
*/

// 原始C代码、长注释和下面的常量都是
// 源代码http:
// http:
// go代码是原始C.
// 
// atan.C 
// 反圆切线（反正切）
// 
// 简介：
// 双x，y，atan（）；
// y=atan（x）；
// 
// 说明：
// 返回切线为x的-pi/2和+pi/2之间的弧度角。
// 
// 范围从三个区间缩小为从零到0.66的区间。
// 近似使用4/5阶有理函数，形式为
// x+x**3p（x）/Q（x）。
// 
// 准确度：
// 相对误差：
// 算术域#试验峰值均方根值
// DEC-10，10 50000 2.4e-17 8.3e-18 
// IEEE-10，10 10^6 1.8e-16 5.0e-17 
// 
// Cephes数学库发行版2.8:2000年6月
// 1984、1987、1989、1992年版权所有，2000年由Stephen L.Moshier 
// 
// 自述文件位于http:
// 此档案中的某些软件可能来自《数学函数的方法和程序》（普伦蒂斯·霍尔或西蒙和舒斯特
// 国际，1989）一书或者从Cephes数学库，
// 商业产品。无论哪种情况，它都是作者的版权。
// 您在这里看到的内容可以免费使用，但不提供任何支持或
// 保证。
// 
// 本书中两个已知的印刷错误在这里的
// 伽马函数和不完整的beta 
// 积分的源代码列表中修复。
// 
// Stephen L.Moshier 
// moshier@na-net.ornl.gov 

// xatan对[0,0.66]范围内有效的系列进行评估。
func xatan(x float64) float64 {
	const (
		P0 = -8.750608600031904122785e-01
		P1 = -1.615753718733365076637e+01
		P2 = -7.500855792314704667340e+01
		P3 = -1.228866684490136173410e+02
		P4 = -6.485021904942025371773e+01
		Q0 = +2.485846490142306297962e+01
		Q1 = +1.650270098316988542046e+02
		Q2 = +4.328810604912902668951e+02
		Q3 = +4.853903996359136964868e+02
		Q4 = +1.945506571482613964425e+02
	)
	z := x * x
	z = z * ((((P0*z+P1)*z+P2)*z+P3)*z + P4) / (((((z+Q0)*z+Q1)*z+Q2)*z+Q3)*z + Q4)
	z = x*z + x
	return z
}

// 撒旦将其参数（已知为正）
// 减少到[0,0.66]范围，并调用xatan。
func satan(x float64) float64 {
	const (
		Morebits = 6.123233995736765886130e-17 // pi/2=PIO2+Morebits 
		Tan3pio8 = 2.41421356237309504880      // tan（3*pi/8）
	)
	if x <= 0.66 {
		return xatan(x)
	}
	if x > Tan3pio8 {
		return Pi/2 - xatan(1/x) + Morebits
	}
	return Pi/4 + xatan((x-1)/(x+1)) + 0.5*Morebits
}

// Atan返回x的反正切值（以弧度为单位）。
// 
// 特殊情况为：
// Atan（±0）=±0 
// Atan（±Inf）=±Pi/2 
func Atan(x float64) float64 {
	if haveArchAtan {
		return archAtan(x)
	}
	return atan(x)
}

func atan(x float64) float64 {
	if x == 0 {
		return x
	}
	if x > 0 {
		return satan(x)
	}
	return -satan(-x)
}
